#include "MainWindow.h"
#include "DocumentCollector.h"

DocumentCollector::DocumentCollector(MainWindow * main_window)
    : _main_window(main_window)
{
    Q_ASSERT(_main_window);

    connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [this](const QString & path) {
                DocumentWindow *            doc_win     = _main_window->findDocumentWindow(path);
                std::shared_ptr<shell::DocumentAdaptor_interface>  
                                            doc_adapter = find(path);

                if (doc_win) {
                    Q_ASSERT(doc_adapter);
                    if (doc_adapter->wasSaved()) {
                        _main_window->sendGlobal(QString("File was saved: %1").arg(path));
                        _watcher.addPath(path);
                    }
                    else {
                        _main_window->sendGlobal(QString("File was changed: %1").arg(path), shell::MessageSeverity::Warning);
                        _main_window->global_messages()->askGlobal(shell::MessageSeverity::Warning,
                                            tr("Noticed a change in the file you opened!"),
                                            tr("The '%1' file you opened has been modified by another application").arg(path),
                                            {
                                                {   tr("Show document"), 
                                                    tr("Make the modified file active"), 
                                                    [this, path](size_t ){
                                                        _main_window->openFile(path);
                                                        return false;
                                                    }},
                                                {   tr("Reload"), 
                                                    tr("Upload changes (the changes you have made will be lost!)"), 
                                                    [this, path](size_t ){
                                                        const std::shared_ptr<shell::DocumentAdaptor_interface> doc_adaptor = _main_window->shell().getDocumentAdaptor(path,false);
                                                        if (doc_adaptor) {
                                                            doc_adaptor->loadFile(path);
                                                            _main_window->sendGlobal(tr("File '%1' reloaded").arg(path));
                                                        }
                                                        return true;
                                                    }},
                                                {   tr("Nothing todo"), 
                                                    tr("Leave everything as it is so that you can save your changes"), 
                                                    nullptr
                                                    },
                                            }, 
                                            "DocumentCollector1");
                    }
                }
                else if (doc_adapter) {
                    _main_window->sendGlobal(QString("File was changed: %1").arg(path));
                    remove(path);
                }
            });
}

DocumentCollector::~DocumentCollector()
{
    // for(shell::DocumentAdaptor_interface * doc_adapter : _docs)
    //     delete doc_adapter;
}

bool DocumentCollector::add(const QString & path, std::shared_ptr<shell::DocumentAdaptor_interface> doc)
{
    auto it = _docs.find(path);
    if (it != _docs.end() && it.key() == path)
        return false;

    _docs.insert(path, doc);
    _watcher.addPath(path);
    return true;
}

bool DocumentCollector::remove(const QString & path)
{
    _watcher.removePath(path);
    // shell::DocumentAdaptor_interface * doc_adapter = find(path);
    // if (doc_adapter) 
    //     delete doc_adapter;
    return _docs.remove(path) == 1;
}

std::shared_ptr<shell::DocumentAdaptor_interface> DocumentCollector::find(const QString & path) const
{
    auto it = _docs.find(path);
    if (it == _docs.end() || it.key() != path)
        return {};

    return it.value();
}

std::optional<QString> DocumentCollector::adaptorPath(const std::shared_ptr<shell::DocumentAdaptor_interface> document_adaptor) const
{
    for (auto & key : _docs.keys())
    {
        if (_docs[key] == document_adaptor)
        {
            return key;
        }
    }

    return {};
}
